/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.filechooser.FileFilter;

import ui.cli.console.Console;
import ui.cli.console.Terminal;
import ui.gui.actions.DocumentAction;
import ui.gui.actions.ExitAction;
import ui.gui.actions.LoadModelAction;
import ui.gui.actions.LoadWorkspaceAction;
import ui.gui.actions.NewRelationAction;
import ui.gui.actions.OpenFileAction;
import ui.gui.actions.SaveAsFileAction;
import ui.gui.actions.SaveFileAction;
import ui.gui.actions.SaveWorkspaceAction;
import ui.gui.actions.ShowAltaricaExplorer;
import ui.gui.actions.ShowSettings;
import ui.gui.actions.ShowWorkspace;
import ui.gui.documents.AbstractDocument;
import ui.gui.documents.DockableDocument;
import ui.gui.documents.EditorAction;
import ui.gui.documents.EditorFactory;
import ui.gui.documents.StartPage;
import ui.gui.documents.toolbox.AbstractToolbox;
import ui.gui.documents.toolbox.AltaricaExplorer;
import ui.gui.documents.toolbox.ToolboxPosition;
import ui.gui.documents.toolbox.Workspace;
import ui.gui.documents.toolbox.WorkspaceExplorer;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.event.CFocusListener;
import bibliothek.gui.dock.common.event.CVetoClosingEvent;
import bibliothek.gui.dock.common.event.CVetoClosingListener;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
/**
 *
 * @author stephane
 */


public class WindowManager extends JFrame implements CVetoClosingListener, CFocusListener
{
    private static WindowManager _instance = null;
    private static final long serialVersionUID = 1L;
    private CGrid _dockManager = null;
    private CControl _control = null;
    private ArrayList<DockableDocument> _documents = null;
    private JMenuBar _mnuBar = new JMenuBar();
    private JToolBar _toolBar = new JToolBar();
    private JMenu _mnuFile = new JMenu();
    private JMenu _mnuView = new JMenu();
    private JMenu _mnuModel = new JMenu();
    private JMenu _mnuDocumentActions = new JMenu();
    private DefaultSingleCDockable _workspaceExplorer  = null;
    private DefaultSingleCDockable _altaricaExplorer  = null;
    private DefaultSingleCDockable _internalConsole  = null;
    private DefaultSingleCDockable _startPageDock = null;
    
    public static WindowManager getInstance()
    {
        if (_instance == null) {
            _instance = new WindowManager();
        }
        
        return _instance;
    }
            
    protected WindowManager()
    {
        this._documents = new ArrayList<DockableDocument>();
        initComponents();
    }
    
    private void buildToolbar() {
    	this._toolBar.removeAll();
        this._toolBar.add(new OpenFileAction(this));
        this._toolBar.add(new SaveFileAction(this));
        this._toolBar.addSeparator();
        this._toolBar.add(new LoadModelAction(this, false));
        _mnuDocumentActions.addSeparator();
        _mnuDocumentActions.addSeparator();
    }
    
    private JMenu createNewDocumentMenu() {
    	JMenu New = new JMenu("Create new document");
    	 for (final AbstractDocument document : EditorFactory.getInstance().getRegisteredEditors()) {
         	New.add(new AbstractAction(document.getFileDescription(), document.getIcon()) {
         		public void actionPerformed(ActionEvent e) {
         			JFileChooser fileChooser = new JFileChooser();
         			fileChooser.setFileFilter(new FileFilter() {
         				@Override
         				public boolean accept(File f) {
         				
         					return f.isDirectory() || f.getName().endsWith(document.getExtension());
         				}
         				@Override
         				public String getDescription() {
         				
         					return document.getFileDescription();
         				}
         			});
         			fileChooser.showSaveDialog(null);
         			File file = fileChooser.getSelectedFile();
         			if (file != null) {
         				if (!file.getName().endsWith(document.getExtension())) {
         					file = new File(file.getAbsolutePath()+document.getExtension());
         				}
	         			AbstractDocument doc = (AbstractDocument)document.clone();
	         			doc.setFile(file);
	         			doc.OnNew();
	         			try {
	         			doc.OnSave();
	         			}
	         			catch (Exception ex) {
	         				
	         			}
	         			Workspace.getInstance().AddDocument(doc);
         			}
         		}
         	});
         }
    	return New;
    }
    
    private void buildMenus() {
        this.setJMenuBar(this._mnuBar);
        this.add(this._toolBar, BorderLayout.NORTH);
        		
        this._mnuBar.add(this._mnuFile);
        this._mnuBar.add(this._mnuView);
        this._mnuBar.add(this._mnuDocumentActions);
        this._mnuBar.add(this._mnuModel);
        
        this._mnuFile.add(createNewDocumentMenu());
        this._mnuFile.addSeparator();
        this._mnuFile.add(new OpenFileAction(this));
        this._mnuFile.add(new SaveFileAction(this));
        this._mnuFile.add(new SaveAsFileAction(this));
        this._mnuFile.addSeparator();
        this._mnuFile.add(new LoadModelAction(this, false));
        this._mnuFile.add(new LoadModelAction(this, true));
        this._mnuFile.addSeparator();
        this._mnuFile.add(new LoadWorkspaceAction(this));
        this._mnuFile.add(new SaveWorkspaceAction(this));
        this._mnuFile.addSeparator();
        this._mnuFile.add(new ExitAction(this));
        
        this._mnuModel.add(new NewRelationAction(this));
        this._mnuModel.addSeparator();
        this._mnuModel.add(new ShowSettings(this));
               
        this._mnuView.add(new ShowWorkspace(this));
        this._mnuView.add(new ShowAltaricaExplorer(this));
        
        this._mnuFile.setText("File");
        this._mnuView.setText("View");
        this._mnuModel.setText("Model");
        this._mnuDocumentActions.setText("Edition");

    }
    private void initComponents()
    {
        _control = new CControl();
        this.setLayout(new BorderLayout());
        this.add(_control.getContentArea(), BorderLayout.CENTER);
        _control.getContentArea().setBorder(BorderFactory.createEmptyBorder(-5,-5,-5,-5));
        _control.setTheme("eclipse");
        _control.setGroupBehavior(CGroupBehavior.TOPMOST);
        
        this.setTitle("CLAC - Compositionnal AltaRica Check");
        this.add(_control.getContentArea() );
        this.setSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
        this.setExtendedState(Frame.MAXIMIZED_BOTH);
        this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        this.addWindowListener(new WindowAdapter() {
        	@Override
        	public void windowClosing(WindowEvent e) {
        		ui.cli.console.Console.getInstance().restoreOriginalOutputStream();
        		System.out.print(Terminal.getPrompt());
        	}
        	@Override
        	public void windowActivated(WindowEvent e) {
        		ui.cli.console.Console.getInstance().restoreEmbeddedConsole();
        		super.windowActivated(e);
        	}
        });
        
        _dockManager = new CGrid( _control );
        
        buildMenus();
        buildToolbar();
        
        _altaricaExplorer = addToolbox(AltaricaExplorer.getInstance(), ToolboxPosition.Left);
        
        _internalConsole = addToolbox(ui.cli.console.Console.getInstance(), ToolboxPosition.BottomLeft);
        _workspaceExplorer = addToolbox(WorkspaceExplorer.getInstance(), ToolboxPosition.Left);
        
        _startPageDock = DockableDocument.fromDocument(new StartPage());
        _startPageDock.setCloseable(false);
        _startPageDock.setTitleShown(false);
        
        _dockManager.add( 100, 0, 400, 1, _startPageDock);
        
        _control.getContentArea().deploy(_dockManager);
        
        _startPageDock.setMaximizable(false);
        _startPageDock.setMinimizable(false);
        _startPageDock.setCloseable(false);
        
        LoadLayout();
        Console.getInstance().restoreOriginalOutputStream();
    }
    private void LoadLayout()
    {
    	 try
         {
         	_control.readXML(new File(".clac.xml"));
         }
         catch (Exception ex)
         {
         	try
         	{
         	StringWriter writer=new StringWriter();
         	InputStreamReader streamReader=new InputStreamReader( WindowManager.class.getResourceAsStream("/resources/.clac.xml"));
         	BufferedReader buffer=new BufferedReader(streamReader);
         	String line="";
         	while ( null!=(line=buffer.readLine())){
         		writer.write(line);
         	}
         	
         	Writer output = new BufferedWriter(new FileWriter(new File(".clac.xml")));;
 	        output.write(writer.toString());
 	        output.close();
         	_control.readXML(new File(".clac.xml"));
         	}
         	catch (Exception exResource)
         	{
         		System.out.println("Unable to load default config\n"+exResource);
         	}
         }

    }
    public void showWorkspaceExplorer() {
        _workspaceExplorer.setVisible(true);
    }
     public void showAltaricaExplorer() {
        _altaricaExplorer.setVisible(true);
    }
    
    public void addWindow(AbstractDocument document) {
    	  addWindow(document, ToolboxPosition.Center);
    }
    public void addWindow(AbstractDocument document, ToolboxPosition position) 
    {
        DockableDocument dockable = DockableDocument.fromDocument(document);
        dockable.addVetoClosingListener(this);
        dockable.setCloseable( true );
        dockable.setTitleShown(document.isTitleShown());
        if (document.getFileName() == null) 
        {
        	document.setIsDirty(true);
        }
        for(DockableDocument d : _documents) {
            d.removeFocusListener(this);
        }
        
        if (position == ToolboxPosition.Right) {
        	_dockManager.add(100, 0, 400, 1, dockable);	
        } 
        else {
            _dockManager.add(100, 0, 400, 1, dockable);
        }
       
         _control.getContentArea().deploy(_dockManager);
         
         dockable.setVisible(true);

         this._documents.add(dockable);
         
          for(DockableDocument d : _documents) {
            d.addFocusListener(this);
         } 
         dockable.setTitleIcon(document.getIcon());
         try
         {
            document.OnLoad();
         }
         catch (Exception ex)
         {
             System.out.println(ex);
         }
         
         
         refreshActions();
         
         
    }
    
    public AbstractDocument getSelectedDocument() {
        for(DockableDocument dock : _documents)
        {
        	
            if (dock.isVisible() && dock.isDockableVisible()) {
              return dock.getDocument();
            }
        }
        return null;
    }
    
    public ArrayList<AbstractDocument> getOpenedDocuments() {
        ArrayList<AbstractDocument> docs = new ArrayList<AbstractDocument>();
        for(DockableDocument dock : _documents)
        {
            if (dock.isVisible()) {
                docs.add(dock.getDocument());
            }
        }
        return docs;
    }
    public void exit()
    {
    	try
    	{
    	_control.writeXML(new File(".clac.xml"));
    	}
    	catch (Exception ex)
    	{
    		System.out.println(ex);
    	}
    }
    
 
    
    public void SelectWindow(AbstractDocument document)
    {
        boolean found = false;
        for (DockableDocument doc : this._documents) {
        	if (doc.getDocument().getFileName().equals( document.getFileName()))
            {
        		
                _dockManager.select(100, 0, 400, 1, doc);
                doc.setVisible(true);
                if (!doc.isVisible())
                {
                    try
                    {
                        doc.getDocument().OnLoad();
                    }
                    catch (Exception ex)
                    {
                        System.out.println(ex);
                    }
                }
                doc.toFront();
                refreshActions();
                found = true;
            }
        }
        
        if (!found) {
            addWindow(document);
        }
        
    }
    
    public DefaultSingleCDockable addToolbox(AbstractToolbox toolbox, ToolboxPosition position ) 
    {
        DefaultSingleCDockable dockable = new DefaultSingleCDockable(toolbox.getTitle(), toolbox.getTitle(), toolbox );
        dockable.setCloseable(true);
        dockable.setMaximizable(false);
        dockable.setTitleIcon(toolbox.getIcon());
        dockable.setResizeRequest(new Dimension(300, 30000), true);
        if (position == ToolboxPosition.Left)
        {
            _dockManager.add( 0, 0, 200, 1, dockable);
        }
        else if (position == ToolboxPosition.Bottom)
        {
            _dockManager.add(0, 800, 400, 1, dockable);
        }
        else if (position == ToolboxPosition.BottomLeft)
        {
           _dockManager.add(0, 200, 200, 1, dockable);
        }
       
        return dockable;
    }

    @Override
    public void closing(CVetoClosingEvent cvce) {
    	DockableDocument dock = (DockableDocument)cvce.getDockable(0);
        if (dock != null && dock.getDocument() != null) {
        	AbstractDocument document = dock.getDocument();
        	if (document.isDirty()) {
        		if (JOptionPane.showConfirmDialog(this, "Do you want close document without saving ?") == JOptionPane.NO_OPTION) {
        			try {
        			document.OnSave();
        			}
        			catch (Exception ex) {
        				System.out.println("Unable to save file");
        				cvce.cancel();
        			}
        		}
        		else if (JOptionPane.showConfirmDialog(this, "Do you want close document without saving ?") == JOptionPane.CANCEL_OPTION) {
        			cvce.cancel();
        		}
        	}
        }
    }

    @Override
    public void closed(CVetoClosingEvent cvce) {
        if (getOpenedDocuments().isEmpty())
        {
            _startPageDock.setVisible(true);
        }
        
    }
    
    public void refreshActions() {
    	 _mnuDocumentActions.removeAll();
         buildToolbar();
         if (getSelectedDocument() != null)
         {
         	for (EditorAction action : getSelectedDocument().getAvailableActions())
         	{
         		if (action != null) {
         			_mnuDocumentActions.add(new DocumentAction(this, action));
         			_toolBar.add(new DocumentAction(this, action));
         		}
         		else
         		{
         			_mnuDocumentActions.addSeparator();
         			_toolBar.addSeparator();
         		}
         	}
         }
         _toolBar.repaint();
         _toolBar.updateUI();
    }

    @Override
    public void focusGained(CDockable cd) {
       refreshActions();
       if (getSelectedDocument() != null) {
    	   getSelectedDocument().refresh();
       }
    }

    @Override
    public void focusLost(CDockable cd) {
        
    }

 
}
